// 伤害系统
library SysDamage requires InitFilter, PropertyUtil, Base

    // 重新计算伤害 不计算系统免伤
    function calcEmenyDamageBase takes unit u, unit bu, real dmv, real xs returns real
        local real def
        local real at
        local real bl
        local real shv = 0

        set def = FF_GetArmor(bu) - FF_GetArmor(bu) * xs
        set at = dmv
        if (def > 0) then
            set bl = 1.0/(1.0 + damaCoefficient*def)
        else
            set bl = 2 - Pow( 0.94, (-1.00 * def))
        endif
        set shv = bl * at

        return shv
    endfunction

    // 计算攻击怪物减少指定百分比护甲后造成的伤害  xs是护甲穿透，0.1表示无视10%的护甲
    function calcEmenyDamage takes unit u, unit bu, real xs returns real
        local real retVal = 0.0
        // local real def
        // local real at
        // local real bl
        // set def = FF_GetArmor(bu) - FF_GetArmor(bu) * xs
        // set at = FF_GetAttack(u)
        // if (def > 0) then
        //     set bl = 1.0/(1.0 + damaCoefficient*def)
        // else
        //     set bl = 2 - Pow( 0.94, (-1.00 * def))
        // endif
        // set retVal = bl * at

        set retVal = calcEmenyDamageBase(u, bu, FF_GetAttack(u), xs)

        set u = null
        set bu = null
        return retVal
    endfunction

    // 重新定义计算伤害函数 
    // xs 护甲减少百分比0.9表示减少90%，伤害系数，系统默认的0.5
    function calcAttackedDamage takes unit u, unit bu, real xs, real shxs returns real
        local real retVal = 0.0
        local real def
        local real at
        local real bl
        set def = FF_GetArmor(bu) - FF_GetArmor(bu) * xs
        set at = FF_GetAttack(u)
        // set at = (GetUnitState( u, ConvertUnitState(0x14)) + GetUnitState( u, ConvertUnitState(0x15))) / 2
        if (def > 0) then
            set bl = 1.0/(1.0 + shxs*def)
        else
            set bl = 2 - Pow( 0.94, (-1.00 * def))
        endif
        set retVal = bl * at

        set u = null
        set bu = null
        return retVal
    endfunction

    function calcAttackedDamage2 takes unit bu, real shv, real xs, real shxs returns real
        local real retVal = 0.0
        local real def
        local real at
        local real bl
        set def = FF_GetArmor(bu) - FF_GetArmor(bu) * xs
        set at = shv
        if (def > 0) then
            set bl = 1.0/(1.0 + shxs*def)
        else
            set bl = 2 - Pow( 0.94, (-1.00 * def))
        endif
        set retVal = bl * at

        set bu = null
        return retVal
    endfunction

    function heroDamagedAction takes nothing returns nothing
        // 记录玩家uid
        local integer uid = GetPlayerId(GetOwningPlayer(GetTriggerUnit()))

        // 英雄
        local unit u = GetTriggerUnit()
        // 怪物
        local unit bu = GetEventDamageSource()

        // 受到的伤害
        local real shv

        // 临时中间值
        local real v

        // 自己伤害自己，队友伤害，一些光环会有这种问题
        if ((GetEventDamageSource() == udg_player_select_hero[0]) or (GetEventDamageSource() == udg_player_select_hero[1]) or (GetEventDamageSource() == udg_player_select_hero[2]) or (GetEventDamageSource() == udg_player_select_hero[3])) then
            // 设置伤害值为0
            call EXSetEventDamage(0.0)

            set u = null
            set bu = null
            return
        endif

        set shv = GetEventDamage()
        if (shv <= 0.0) then
            set u = null
            set bu = null
            return
        endif

        // 重新计算伤害
        if not YDWEIsEventDamageType(DAMAGE_TYPE_DIVINE) then
            if YDWEIsEventAttackType(ATTACK_TYPE_NORMAL) then
                // 法术伤害
                set shv = calcAttackedDamage2(u, GetEventDamage(), udg_diff_hurt_ct[udg_game_diff], udg_diff_xs_qtg[udg_game_diff])
            else
                // 物理攻击伤害
                set shv = calcAttackedDamage(bu, u, udg_diff_hurt_ct[udg_game_diff], udg_diff_xs_qtg[udg_game_diff])
            endif
        else
            // 真实伤害都是触发造成的，无需重新计算模拟
            set shv = GetEventDamage()
        endif
        call EXSetEventDamage(0.0)


        // call BJDebugMsg("英雄生命值:" + R2S(FF_GetHp(u)))
        // call BJDebugMsg("英雄受到的伤害：" + R2S(GetEventDamage()))

        set v = FF_GetHp(u) - shv
        if v <= 1.00 then
            set v = 0.0
        endif
        call FF_SetHp(u, v)
        // 防止有些没有设置自定义最大生命值
        if FF_GetMaxHp(u) == 0.0 then
            call FF_SetMaxHp(u, 1.0)
        endif
        // 显示血条百分比
        call SetUnitLifePercentBJ( u, FF_GetHp(u) / FF_GetMaxHp(u) * 100 )
        if FF_GetHp(u) <= 1.00 then
            call EXSetEventDamage(2000.0)
        endif

        set u = null
        set bu = null
    endfunction

    function enemyDamagedAction takes nothing returns nothing

        local integer uid = GetPlayerId(GetOwningPlayer(GetEventDamageSource()))
        // 伤害单位 英雄
        local unit u = GetEventDamageSource()
        // 触发单位 怪物
        local unit bu = GetTriggerUnit()
        local real shv = GetEventDamage()
        local real v
        local real wsHj = 0.0

        local group g
        local unit temp_u
        local boolexpr filter

        // 是否暴击
        local boolean isCrit = false
        local real angle

        // call BJDebugMsg("单位收到伤害")

        // 对一些特殊单位无法造成伤害
        if u == bu then
            call EXSetEventDamage(0.00)
        endif

        // 没有伤害直接结束
        if (shv == 0.00) then
            set u = null
            set bu = null
            set g = null
            set filter = null
            return 
        endif

        // 重新计算伤害
        // set shv = GetEventDamage()
        // if YDWEIsEventAttackDamage() then
        //     // 物理攻击伤害
        //     set shv = calcEmenyDamage(u, bu, wsHj)
        // else
        //     // 法术
        //     if YDWEIsEventDamageType(DAMAGE_TYPE_DIVINE) then
        //         // 真实伤害都是触发造成的真实伤害，无需重新计算模拟
        //         set shv = GetEventDamage()
        //     else
        //         set shv = calcEmenyDamageBase(u, bu, GetEventDamage(), wsHj)
        //     endif
        // endif

        // if YDWEIsEventDamageType(DAMAGE_TYPE_NORMAL) then
        //     call BJDebugMsg("普通伤害 --> " + R2S(GetEventDamage()))
        // elseif YDWEIsEventDamageType(DAMAGE_TYPE_ENHANCED) then
        //     call BJDebugMsg("增强伤害 --> " + R2S(GetEventDamage()))
        // elseif YDWEIsEventDamageType(DAMAGE_TYPE_FIRE) then
        //     call BJDebugMsg("火焰伤害 --> " + R2S(GetEventDamage()))
        // elseif YDWEIsEventDamageType(DAMAGE_TYPE_COLD) then
        //     call BJDebugMsg("冰霜伤害 --> " + R2S(GetEventDamage()))
        // elseif YDWEIsEventDamageType(DAMAGE_TYPE_LIGHTNING) then
        //     call BJDebugMsg("闪电伤害 --> " + R2S(GetEventDamage()))
        // elseif YDWEIsEventDamageType(DAMAGE_TYPE_POISON) then
        //     call BJDebugMsg("毒素伤害 --> " + R2S(GetEventDamage()))
        // elseif YDWEIsEventDamageType(DAMAGE_TYPE_SPIRIT_LINK) then
        //     call BJDebugMsg("灵魂链接伤害 --> " + R2S(GetEventDamage()))
        // elseif YDWEIsEventDamageType(DAMAGE_TYPE_DIVINE) then
        //     call BJDebugMsg("神圣伤害 --> " + R2S(GetEventDamage()))
        // endif

        // 闪电链
        if GetUnitTypeId(u) == 'N002' then
            call EXSetEventDamage(0.0)
            call UnitDamageTarget( udg_player_select_hero[uid], bu, FF_GetAttack(udg_player_select_hero[uid]) * 0.5 * (1.0 + ct_sdlDmgZf[uid]), true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_LIGHTNING, WEAPON_TYPE_METAL_HEAVY_SLICE )
            // 如果持续伤害则添加到持续伤害单位组中
            if ct_sdlIsChixu[uid] and FF_GetHp(bu) >= 1 then
                call GroupAddUnit(LoadGroupHandle(sdlHash, uid, 1), bu)
            endif
            return 
        endif

        // 法术
        if YDWEIsEventDamageType(DAMAGE_TYPE_DIVINE) then
            // 真实伤害都是触发造成的真实伤害，无需重新计算模拟
            set shv = GetEventDamage()
        else
            set shv = calcEmenyDamageBase(u, bu, GetEventDamage(), wsHj)
        endif

        // call EXSetEventDamage(0.0)
        call EXSetEventDamage(shv)
        // call BJDebugMsg("单位收到伤害: " + R2S(shv))

        // 放到最后，处决单位（模拟单位的所有真实生命值为1000
        // 百分比生命转换
        // 当前生命值 - 造成的伤害 = 剩余生命值
        // 剩余生命值 / 最大生命值 * 100 = 剩余百分比
        // 剩余生命值如果小于等于1，则直接处决
        set v = FF_GetHp(bu) - shv
        if v <= 1.00 then
            set v = 0.0
        endif
        call FF_SetHp(bu, v)
        // 防止有些没有设置自定义最大生命值
        if FF_GetMaxHp(bu) == 0.0 then
            call FF_SetMaxHp(bu, 1.0)
        endif
        // 显示血条百分比
        // call SetUnitLifePercentBJ( bu, FF_GetHp(bu) / FF_GetMaxHp(bu) * 100 )
        // if FF_GetHp(bu) <= 1.00 then
        //     call EXSetEventDamage(2000.0)
        // endif

        set shv = GetEventDamage()
        // 普通伤害，白色的
        if YDWEIsEventDamageType(DAMAGE_TYPE_NORMAL) then
            call showSHWZ(uid, R2I(shv), 0, GetUnitX(bu), GetUnitY(bu))
        // 火焰伤害，红色的
        elseif YDWEIsEventDamageType(DAMAGE_TYPE_FIRE) then
            call showSHWZ(uid, R2I(shv), 1, GetUnitX(bu), GetUnitY(bu))
        // 增强伤害，蓝色的，用于通用法术伤害
        elseif YDWEIsEventDamageType(DAMAGE_TYPE_ENHANCED) then
            call showSHWZ(uid, R2I(shv), 2, GetUnitX(bu), GetUnitY(bu))
        // 闪电伤害，黄色的
        elseif YDWEIsEventDamageType(DAMAGE_TYPE_LIGHTNING) then
            call showSHWZ(uid, R2I(shv), 4, GetUnitX(bu), GetUnitY(bu))
        // 冰霜伤害 绿色的
        elseif YDWEIsEventDamageType(DAMAGE_TYPE_COLD) then
            call showSHWZ(uid, R2I(shv), 3, GetUnitX(bu), GetUnitY(bu))
        endif

        set u = null
        set bu = null
        set temp_u = null
        set g = null
        set filter = null
    endfunction

endlibrary

